import tornado.web
import tornado.websocket
import tornado.httpserver
import tornado.ioloop
import tornado.escape
import json
import logging
from sexyDealer import SexyDealer
import uuid


class Player:
    def __init__(self, name, id, cards):
        self.name = name
        self.id = id
        self.cards = cards


linkers = set()
room = {}
dealer = {}


class WebSocketHandler(tornado.websocket.WebSocketHandler):
    player_amount = 1

    def check_origin(self, origin):
        return True

    def open(self):
        self.write_message({'type': 'accessible', 'data': {'accessible': 'true'}})
        # self.waiters.add(self)

    def on_message(self, message):
        parsed = tornado.escape.json_decode(message)
        types = parsed['type']
        data = parsed['data']
        room_id = 1
        player_amount = 1
        print(message)
        if types == 'enter_room':
            name = data['name']
            self.username = name
            self.pid = str(uuid.uuid1())
            self.room_id = room_id
            self.ready = False
            self.enter = True
            for i in linkers:
                if i.room_id == room_id:
                    player_amount += 1
            room[room_id] = {player_amount}
            linkers.add(self)
            self.write_message({'type': 'room_info', 'data': {'others': [
                {
                    'name': self.username,
                    'amount': str(room[room_id]),
                }
            ], 'id': self.pid}})
        if types == 'ready':
            # if len(self.user_dict) == 3:
            #     for i in self.waiters:
            #         card = self.sexy_dealer.deal()
            #         i.write_message({'type': 'game_begins', 'data': {
            #             'cards': card,
            #             'other': [
            #                 {
            #                     'name': self.user_dict[data['id']]['name'],
            #                     'card_amt': len(card),
            #                 },
            #             ],
            #         }})
            ready_num = 0
            enter_num = 0
            # 获得room_id
            for i in linkers:
                if data['id'] == i.pid:
                    i.ready = True
            for i in linkers:
                if i.ready is True and i.room_id == room_id:
                    ready_num = ready_num + 1
            for i in linkers:
                if i.enter is True and i.room_id == room_id:
                    enter_num = enter_num + 1
            if ready_num == enter_num and ready_num == 2:
                self.generate_dealer(room_id, ready_num)
            elif ready_num == enter_num and ready_num == 4:
                self.generate_dealer(room_id, ready_num)
        if types == 'can_i_play':
            if dealer[room_id].canIPlay(data['id']) is True:
                self.write_message({'type': 'play_status', 'data': {'status': 'true'}})
            else:
                self.write_message({'type': 'play_status', 'data': {'status': 'false'}})
        if types == 'play':
            # result = dealer[room_id].handle_play(data['id'], str(data['cards']).strip('[]').split(','), data['statement'])
            result = dealer[room_id].handle_play(data['id'], data['cards'], data['statement'])
            if type(result) == list:
                for i in linkers:
                    if self.pid == i.pid:
                        i.cards = result[3]
                    i.write_message(
                        {'type': 'play_result',
                         'data': {'message': self.username + '出了' + str(result[1]) + '张' + result[2],
                                  'others': [{'name': self.username, 'amounts': len(result[3])}], 'id': self.pid}})
            else:
                self.write_message({'type': 'info', 'data': {'result': result}})
        if types == 'challenge':
            print(data['id'])
            result = dealer[room_id].handle_challenge(data['id'])
            if type(result) == list:
                for i in linkers:
                    if i.pid == result[2]:
                        i.cards = result[1]
                for i in linkers:
                    i.write_message({'type': 'chanllenge_result',
                                     'data': {'message': result[0],
                                              'id': result[2],'name':result[1]}})
            else:
                self.write_message({'type': 'info', 'data': {'result': result}})
        if types == 'pass':
            result = dealer[room_id].handle_pass(data['id'])
            return result

    # def on_close(self):
    #     linkers.remove(self)
    # 广播
    @classmethod
    def send_updates(cls, data, room_id=None):
        # logging.info("sending message to %d waiters", len(self.waiters))
        # for waiter in self.waiters:
        #     try:
        #         waiter.write_message(data)
        #     except:
        #         logging.error("Error sending message", exc_info=True)
        if room_id != None:
            for i in linkers:
                if i.room_id == room_id:
                    i.write_message(data)
        else:
            for i in linkers:
                i.write_message(data)

    @staticmethod
    def generate_dealer(room_id, player_amount):
        dealer[room_id] = SexyDealer(player_amount)
        for i in linkers:
            if i.room_id == room_id:
                dealer[room_id].nextId = i.pid
                break
        dealer[room_id].shuffle()
        for i in linkers:
            if i.room_id == room_id:
                i.cards = dealer[room_id].deal()
                player = Player(i.username, i.pid, i.cards)
                dealer[room_id].add_user(player)
                i.write_message({'type': 'game_begins', 'data': {
                    'cards': i.cards,
                    'other': [
                        {
                            'name': i.username,
                            'card_amt': len(i.cards),
                        },
                    ],
                }})

    @staticmethod
    def close_room(room_id):
        for i in linkers:
            if i.room_id == room_id:
                i.enter = False
                i.ready = False
                i.room_id = None

    def on_close(self):
        linkers.remove(self)
        self.close(self)


class IndexPageHandler(tornado.web.RequestHandler):
    def get(self):
        self.render("websocket.html")


class Application(tornado.web.Application):
    def __init__(self):
        handlers = [
            (r'/', IndexPageHandler),
            (r'/cnb', WebSocketHandler)
        ]
        settings = {
            'template_path': 'static'
        }
        tornado.web.Application.__init__(self, handlers, **settings)


if __name__ == '__main__':
    ws_app = Application()
    server = tornado.httpserver.HTTPServer(ws_app)
    server.listen(5002)
    tornado.ioloop.IOLoop.instance().start()
